home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / FLOATING / PROCEDUR / SOURCE_C / FLOATING.C next >
Text File  |  1990-10-30  |  15KB  |  520 lines

  1. /********************************************************************
  2.     FLOATING WINDOWS 1.3
  3.     Copyright 1990 Patrick Doane. All Rights Reserved
  4.  ********************************************************************/
  5.  
  6. #include "Floating.h"
  7.  
  8. WindowPtr    bottomFloat,topFloat,topWindow;
  9. RgnHandle    drawRgn,windowRgn,dragRgn;
  10. GrafPtr        wPort;
  11. Rect        dragRect;
  12.  
  13. void    InitFloat(void)
  14. {
  15.     /* Initialize all of the internal variables */
  16.     drawRgn = NewRgn();
  17.     windowRgn = NewRgn();
  18.     dragRgn = NewRgn();
  19.     
  20.     wPort = (GrafPtr)NewPtrClear(sizeof(GrafPort));
  21.     OpenPort(wPort);
  22.     
  23.     topFloat = 0L;
  24.     bottomFloat = 0L;
  25.     topWindow = 0L;
  26.     
  27.     dragRect = (**GetGrayRgn()).rgnBBox;
  28.     InsetRect(&dragRect,4,4);
  29. }
  30.  
  31. void    UpdateTopWindow(void)
  32. {
  33.     if (bottomFloat)
  34.         topWindow = (WindowPtr)((WindowPeek)bottomFloat)->nextWindow;
  35.     else
  36.         topWindow = FrontWindow();
  37. }
  38.  
  39. void    UpdateFloats(void)
  40. {
  41.     WindowPeek    theWindow;
  42.     
  43.     topFloat = 0L;                            /* Clear variables */
  44.     bottomFloat = 0L;
  45.     theWindow = (WindowPeek)FrontWindow();    /* Start with the front window */
  46.     if (IsFloating((WindowPtr)theWindow))    /* Is it a floating window? */
  47.     {    topFloat = (WindowPtr)theWindow;    /* Yep, let's start figuring
  48.                                                out our list starting with
  49.                                                that one */
  50.      
  51.         while (IsFloating((WindowPtr)theWindow))
  52.         {    /* Continue updating our bottom pointer until we have found the
  53.                the last window */
  54.             bottomFloat = (WindowPtr)theWindow;
  55.             theWindow = theWindow->nextWindow;
  56.             if (!theWindow)
  57.                 break;
  58.         }
  59.     }
  60. }
  61.  
  62. WindowPtr    NewFloatingWindow(short ResID,Ptr wStorage)
  63. {
  64.     WindowPtr    theWindow;
  65.     
  66.                                     /* Bring it into existance */
  67.     theWindow = GetNewWindow(ResID,wStorage,0L);
  68.     
  69.     BringToFront(theWindow);        /* Floating window must be in front */
  70.     ShowHide(theWindow,true);        /* Make sure it is visible */
  71.     if (!topFloat)                    /* If topFloat is 0L then this is the
  72.                                        the first floating window to be
  73.                                        made. Since it is the first, it must
  74.                                        also be the last */
  75.         bottomFloat = theWindow;
  76.     
  77.     topFloat = theWindow;            /* Mark it is as the top floating window */
  78.     
  79.     MakeFloating(theWindow);        /* And mark it as a floating window */
  80.     
  81.     return theWindow;                /* Return reference to theWindow */
  82. }
  83.  
  84. void    MakeFloating(WindowPtr whichWindow)
  85. {
  86.                                     /* Mark it as a floating window */
  87.     ((WindowPeek)whichWindow)->windowKind = 317;
  88.     BringToFront(whichWindow);        /* Floating window must be in front */
  89. }
  90.  
  91. Boolean    IsFloating(WindowPtr whichWindow)
  92. {
  93.                                     /* Is it a floating window? */
  94.     return (((WindowPeek)whichWindow)->windowKind == 317);
  95. }
  96.  
  97. void    CloseTheWindow(WindowPtr whichWindow)
  98. {
  99.     register WindowPeek    theWindow;
  100.     
  101.     CloseWindow(whichWindow);
  102.     
  103.     /* Calculate the next window to hilite. Start with the next window
  104.        behind the one you are closing. Continue until you find the first
  105.        visable one. */
  106.     
  107.     theWindow = ((WindowPeek)whichWindow)->nextWindow;
  108.     if (theWindow)
  109.     {    while (!theWindow->visible)
  110.         {    theWindow = theWindow->nextWindow;
  111.             if (!theWindow)
  112.                 break;
  113.         }
  114.     }
  115.     
  116.     /* If we got a window (other than 0L) then Hilite it and tell the
  117.        toolbox to activate that window */
  118.     if (theWindow)
  119.     {    HiliteWindow(theWindow,true);
  120.         CurActivate = (WindowPtr)theWindow;
  121.         /* Since one of the windows that was killed could have been a floating
  122.            window. We rebuild that list starting with the frontmost window
  123.            and working the way through the list until we find the first
  124.            nonfloating window which marks the end of the floats. */
  125.         
  126.         UpdateFloats();
  127.     }
  128.     else        /* We have no windows left so hide our floats */
  129.         HideFloats();
  130.     UpdateTopWindow();
  131. }
  132.  
  133. void    DisposeTheWindow(WindowPtr whichWindow)
  134. {
  135.     register WindowPeek    theWindow;
  136.     
  137.     DisposeWindow(whichWindow);
  138.     
  139.     /* Calculate the next window to hilite. Start with the next window
  140.        behind the one you are closing. Continue until you find the first
  141.        visable one. */
  142.     
  143.     theWindow = ((WindowPeek)whichWindow)->nextWindow;
  144.     if (theWindow)
  145.     {    while (!theWindow->visible)
  146.         {    theWindow = theWindow->nextWindow;
  147.             if (!theWindow)
  148.                 break;
  149.         }
  150.     }
  151.     
  152.     /* If we got a window (other than 0L) then Hilite it and tell the
  153.        toolbox to activate that window */
  154.     if (theWindow)
  155.     {    HiliteWindow((WindowPtr)theWindow,true);
  156.         CurActivate = (WindowPtr)theWindow;
  157.         /* Since one of the windows that was killed could have been a floating
  158.            window. We rebuild that list starting with the frontmost window
  159.            and working the way through the list until we find the first
  160.            nonfloating window which marks the end of the floats. */
  161.         
  162.         UpdateFloats();
  163.     }
  164.     else        /* We have no windows left so hide our floats */
  165.         HideFloats();
  166.     UpdateTopWindow();
  167. }
  168.  
  169. void    ShowTheWindow(WindowPtr whichWindow)
  170. {
  171.     ShowWindow(whichWindow);            /* Call Toolbox Procedure */
  172.     
  173.     if (whichWindow == (WindowPtr)((WindowPeek)bottomFloat)->nextWindow)
  174.                                         /* If the window is now the
  175.                                            top nonfloating window,
  176.                                            Hilite it */
  177.         HiliteWindow(whichWindow,true);
  178.     UpdateFloats();
  179. }
  180.  
  181. void    HideTheWindow(WindowPtr whichWindow)
  182. {
  183.     register WindowPeek    theWindow;
  184.     
  185.     HideWindow(whichWindow);            /* Call Toolbox procedure */
  186.     
  187.     /* Start with the next window behind the one we are hiding.
  188.        Continue searching until we find a visible one. */
  189.     
  190.     theWindow = ((WindowPeek)whichWindow)->nextWindow;
  191.     while (!theWindow->visible)
  192.     {    theWindow = theWindow->nextWindow;
  193.         if (!theWindow)
  194.             break;
  195.     }
  196.     
  197.     if (theWindow)                        /* If we found a window, Hilite it */
  198.         HiliteWindow(theWindow,true);
  199.     UpdateFloats();
  200. }
  201.  
  202. void    ShowFloats(void)
  203. {
  204.     register WindowPeek    theWindow;
  205.     
  206.     if (topFloat)                            /* Do we have floating windows? */
  207.     {    theWindow = (WindowPeek)topFloat;    /* Start with the top one */
  208.         
  209.         while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
  210.                                             /* Contine until we reach the
  211.                                                last floating window */
  212.         
  213.         {                                    /* Show the window and move
  214.                                                on to the next */
  215.             ShowHide((WindowPtr)theWindow,true);
  216.             theWindow = theWindow->nextWindow;
  217.             if (!theWindow)
  218.                 break;
  219.         }
  220.     }
  221. }
  222.  
  223. void    HideFloats(void)
  224. {
  225.     register WindowPeek    theWindow;
  226.     
  227.     if (topFloat)                            /* Do we have floating windows? */
  228.     {    theWindow = (WindowPeek)topFloat;    /* Start with the top one */
  229.         
  230.         while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
  231.                                             /* Contine until we reach the
  232.                                                last floating window */
  233.         
  234.         {                                    /* Hide the window and move
  235.                                                on to the next */
  236.             ShowHide((WindowPtr)theWindow,false);
  237.             theWindow = theWindow->nextWindow;
  238.             if (!theWindow)
  239.                 break;
  240.         }
  241.     }
  242. }
  243.  
  244. WindowPtr    CurrentWindow(void)
  245. {
  246.     return topWindow;                        /* Just return our variable */
  247. }
  248.  
  249. void    SelectTheWindow(register WindowPtr whichWindow)
  250. {
  251.     Boolean                floating;            /* Is it a floating window */
  252.     register WindowPeek    bottomPeek;            /* Reference to bottom float */
  253.     register WindowPeek    theWindowPeek;        /* Generic reference to window */
  254.     WindowPtr            lastTop;            /* The last top window */
  255.     register WindowPeek    beforePeek;            /* The location of where the
  256.                                                the window will be moved */
  257.     GrafPtr                savePort;
  258.     
  259.     floating = IsFloating(whichWindow);        /* Is it a floating window? */
  260.     
  261.     if (floating)
  262.     {    if (whichWindow != topFloat)
  263.         {    /* If it is not the front floating window, bring it to the front */
  264.             BringToFront(whichWindow);
  265.             topFloat = whichWindow;
  266.             
  267.             /* and find the last floating window */
  268.             theWindowPeek = (WindowPeek)whichWindow;
  269.             while (IsFloating((WindowPtr)theWindowPeek))
  270.             {    bottomFloat = (WindowPtr)theWindowPeek;
  271.                 theWindowPeek = theWindowPeek->nextWindow;
  272.             }
  273.         }
  274.     }
  275.     else
  276.     {    if (!bottomFloat)    /* if there are no other floating windows
  277.                                just bring it to the front. */
  278.         {    if (whichWindow != FrontWindow())
  279.                 SelectWindow(whichWindow);
  280.         }
  281.         else
  282.         {    bottomPeek = (WindowPeek)bottomFloat;
  283.             theWindowPeek = (WindowPeek)whichWindow;
  284.             
  285.             if (theWindowPeek != bottomPeek->nextWindow)
  286.             {    /* It's not the top document window, now we find what
  287.                    that is */
  288.                 lastTop = (WindowPtr)bottomPeek->nextWindow;
  289.                 
  290.                 /* Create deactivate event for last active document window */
  291.                 CurDeactive = lastTop;
  292.                 HiliteWindow(lastTop,false);
  293.                 
  294.                 /* Now we rewrite the window list to change the location
  295.                    of the window. First we find the window that was before
  296.                    the window we want to move. We then set its nextWindow
  297.                    field to the window in front of the window we are moving.
  298.                    That then removes the window from the window list.
  299.                    Now we want to place it rigth after the bottommost
  300.                    floating window. To do that, we set the nextWindow
  301.                    field of the window we are moving to the window right
  302.                    after the bottommost floating window and set the nextWindow
  303.                    field of the bottommost floating window to the window
  304.                    we are moving. Confusing eh? */
  305.                 
  306.                 beforePeek = bottomPeek->nextWindow;
  307.                 while (beforePeek->nextWindow != theWindowPeek)
  308.                     beforePeek = beforePeek->nextWindow;
  309.                 beforePeek->nextWindow = theWindowPeek->nextWindow;
  310.                 
  311.                 theWindowPeek->nextWindow = bottomPeek->nextWindow;
  312.                 bottomPeek->nextWindow = theWindowPeek;
  313.                 
  314.                 /* Now we have to recalculate all the visible regions
  315.                    and redraw newly exposed areas */
  316.                 
  317.                 GetPort(&savePort);
  318.                 SetPort(whichWindow);
  319.                 
  320.                 /* We start with the visible region of our window but
  321.                    unfortunately, it is in local coordinates of the
  322.                    window so we convert it to global by using the GlobalRgn
  323.                    procedure */
  324.                 
  325.                 CopyRgn(whichWindow->visRgn,drawRgn);
  326.                 GlobalRgn(drawRgn);
  327.                 
  328.                 /* We then subtract the visible region of the window
  329.                    from the windows structure region. This gives us
  330.                    the area which is being brought to the front */
  331.                 
  332.                 DiffRgn(theWindowPeek->strucRgn,drawRgn,drawRgn);
  333.                 
  334.                 /* Paint the area and hilite it to show it is now active */
  335.                 PaintOne(whichWindow,drawRgn);
  336.                 HiliteWindow(whichWindow,true);
  337.                 
  338.                 /* PaintOne sets thePort to the Window Manager Port so
  339.                    we must reset thePort to whichWindow. We then call
  340.                    CalcWindowVis which will recalculate all the visible
  341.                    regions */
  342.                 
  343.                 SetPort(whichWindow);
  344.                 CalcWindowVis(theWindowPeek);
  345.                 
  346.                 /* Then invalidate the region so that it will update
  347.                    properly */
  348.                 
  349.                 InvalRgn(drawRgn);
  350.                 SetPort(savePort);
  351.                 
  352.                 /* And finally, generate another event to activate the
  353.                    new window */
  354.                 
  355.                 CurActivate = whichWindow;
  356.             }
  357.         }
  358.     }
  359.     if (!((WindowPeek)whichWindow)->visible)    /* A little kludge
  360.                                has been added for floating window support
  361.                                which makes sure to make the window visible
  362.                                if it is hidden */
  363.         ShowHide(whichWindow,true);
  364.                 
  365.     UpdateTopWindow();        /* Rebuild our window list */
  366. }
  367.  
  368. void    DragTheWindow(WindowPtr whichWindow,EventRecord *theEvent)
  369. {
  370.     GrafPtr                savePort;        /* Saved graphics pointer */
  371.     Point                thePoint;        /* Used to remember the original
  372.                                            location of the window */
  373.     long                newLoc;            /* Window's new position */
  374.     short                hDelta,vDelta;    /* How much to move the window */
  375.     register WindowPeek    theWindow;
  376.     
  377.     /* Since dragging a window automatically brings it to the front
  378.        unless you are holding the command key down, this routine needs
  379.        to be redone. Otherwise it would kill the floating window
  380.        relationship */
  381.     
  382.     /* If it's a floating window and not the front floating window
  383.        and the command key is not down, bring it to the front before
  384.        draggin */
  385.     if (IsFloating(whichWindow))
  386.     {    if (whichWindow != topFloat && !(theEvent->modifiers & cmdKey))
  387.             SelectTheWindow(whichWindow);
  388.     }
  389.     /* if the window is not the front document window and the command
  390.        key is not down, select the window and exit */
  391.     
  392.     else if (!topFloat)
  393.     {    if (whichWindow != FrontWindow() && !(theEvent->modifiers & cmdKey))
  394.         {    SelectWindow(whichWindow);
  395.             return;
  396.         }
  397.     }
  398.     else if (whichWindow != (WindowPtr)((WindowPeek)bottomFloat)->nextWindow
  399.         && !(theEvent->modifiers & cmdKey))
  400.     {    SelectTheWindow(whichWindow);
  401.         return;
  402.     }
  403.     
  404.     if (!StillDown())
  405.         return;
  406.     
  407.     GetPort(&savePort);
  408.     SetPort(whichWindow);
  409.     
  410.     /* remember the top-left coordinate of the window */
  411.     thePoint = topLeft(whichWindow->portRect);
  412.     LocalToGlobal(&thePoint);
  413.     
  414.     
  415.     /* Copy the window's structure region to be used for dragging */
  416.     CopyRgn(((WindowPeek)whichWindow)->strucRgn,dragRgn);
  417.     
  418.     /* Use our graphics port */
  419.     SetPort(wPort);
  420.     
  421.     /* We must figure out the drag region for the window.
  422.        Start with the top window and work or way through the window
  423.        list altering our graphics port to the screen's visible region.
  424.        This effectively gives us a visible region of the screen minus
  425.        that of all windows above the window we are dragging */
  426.     
  427.     CopyRgn(GetGrayRgn(),wPort->visRgn);
  428.     
  429.     theWindow = (WindowPeek)FrontWindow();
  430.     if (theWindow != (WindowPeek)whichWindow)
  431.     {    DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
  432.         while (theWindow != (WindowPeek)whichWindow)
  433.         {    DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
  434.             theWindow = theWindow->nextWindow;
  435.         }
  436.     }
  437.     
  438.     /* drag the window */
  439.     newLoc = DragGrayRgn(dragRgn,theEvent->where,&dragRect,&dragRect,
  440.         noConstraint,0L);
  441.     if (newLoc != 0x80008000)
  442.     {    hDelta = LoWord(newLoc);
  443.         vDelta = HiWord(newLoc);
  444.         
  445.         /* If the window moved, move it */
  446.         if (hDelta || vDelta)
  447.             MoveWindow(whichWindow,hDelta+thePoint.h,vDelta+thePoint.v,false);
  448.     }
  449.     SetPort(savePort);
  450. }
  451.  
  452. void    CalcWindowVis(register WindowPeek whichWindow)
  453. {
  454.     register WindowPeek    theWindow;
  455.     GrafPtr                savePort;
  456.     
  457.     GetPort(&savePort);
  458.     
  459.     /* First we start with an empty region. From there we begin with
  460.        the front window which would be one of the floating windows
  461.        and add its structure region to windowRgn. We continue to add
  462.        in the regions until we reach whichWindow */
  463.     
  464.     SetEmptyRgn(windowRgn);
  465.     theWindow = (WindowPeek)FrontWindow();
  466.     while (theWindow != whichWindow)
  467.     {    UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
  468.         theWindow = theWindow->nextWindow;
  469.     }
  470.     
  471.     /* We now have all the regions of all the windows in front of
  472.        whichWindow. To calculate the visible region of whichWindow,
  473.        we copy its content region (which is in global coordinates) into
  474.        the visRgn field. We then SUBTRACT the region we generated before
  475.        from the visible region of the window. Finally, convert it into
  476.        local coordinates for the toolbox */
  477.     
  478.     SetPort(whichWindow);
  479.     CopyRgn(whichWindow->contRgn,whichWindow->port.visRgn);
  480.     DiffRgn(whichWindow->port.visRgn,windowRgn,whichWindow->port.visRgn);
  481.     LocalRgn(whichWindow->port.visRgn);
  482.     
  483.     /* Now we have to calculate all the visible regions for all windows
  484.        behind whichWindow. We just go through the same process again
  485.        and again, but each time we add the window's structure region
  486.        into windowRgn to subtract again. */
  487.     
  488.     theWindow = whichWindow;
  489.     while (theWindow->nextWindow)
  490.     {    UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
  491.         
  492.         theWindow = theWindow->nextWindow;
  493.         
  494.         SetPort(theWindow);
  495.         CopyRgn(theWindow->contRgn,theWindow->port.visRgn);
  496.         DiffRgn(theWindow->port.visRgn,windowRgn,theWindow->port.visRgn);
  497.         LocalRgn(theWindow->port.visRgn);
  498.     }
  499.     SetPort(savePort);
  500. }
  501.  
  502. void    GlobalRgn(register RgnHandle changeRgn)
  503. {
  504.     register Rect    theRect;
  505.     
  506.     /* Converts a region into Global Coordinates */
  507.     
  508.     theRect = thePort->portBits.bounds;
  509.     OffsetRgn(changeRgn,-theRect.left,-theRect.top);
  510. }
  511.  
  512. void    LocalRgn(register RgnHandle changeRgn)
  513. {
  514.     register Rect    theRect;
  515.     
  516.     /* Converts a region into Global Coordinates */
  517.     
  518.     theRect = thePort->portBits.bounds;
  519.     OffsetRgn(changeRgn,theRect.left,theRect.top);
  520. }